package classfile

type MemberInfo struct {
	__constantPool__ ConstantPool
	accessFlags      uint16
	nameIndex        uint16
	descriptorIndex  uint16
	attributesCount  uint16
	attributes       []AttributeInfo
}

func (self *MemberInfo) ConstantValueAttribute() *ConstantValueAttribute {
	for _, attrInfo := range self.attributes {
		switch attrInfo.(type) {
		case *ConstantValueAttribute:
			return attrInfo.(*ConstantValueAttribute)
		}
	}
	return nil
}

func readMembers(reader *ClassReader, count uint16, constantPool ConstantPool) []*MemberInfo {
	members := make([]*MemberInfo, count)
	for i := range members {
		members[i] = readMember(reader, constantPool)
	}
	return members
}

func readMember(reader *ClassReader, constantPool ConstantPool) *MemberInfo {
	accessFlags := reader.readUint16()
	nameIndex := reader.readUint16()
	descriptorIndex := reader.readUint16()
	attributesCount := reader.readUint16()
	return &MemberInfo{
		__constantPool__: constantPool,
		accessFlags:      accessFlags,
		nameIndex:        nameIndex,
		descriptorIndex:  descriptorIndex,
		attributesCount:  attributesCount,
		attributes:       readAttributes(reader, attributesCount, constantPool),
	}
}

func (self *MemberInfo) Name() string {
	return self.__constantPool__.getUtf8(self.nameIndex)
}

func (self *MemberInfo) Descriptor() string {
	return self.__constantPool__.getUtf8(self.descriptorIndex)
}

func (self *MemberInfo) CodeAttribute() *CodeAttribute {
	for _, attrInfo := range self.attributes {
		switch attrInfo.(type) {
		case *CodeAttribute:
			return attrInfo.(*CodeAttribute)
		}
	}
	return nil
}

func (self *MemberInfo) AccessFlags() uint16 {
	return self.accessFlags
}

func (self *MemberInfo) ExceptionsAttribute() *ExceptionsAttribute {
	for _, attrInfo := range self.attributes {
		switch attrInfo.(type) {
		case *ExceptionsAttribute:
			return attrInfo.(*ExceptionsAttribute)
		}
	}
	return nil
}

func (self *MemberInfo) RuntimeVisibleAnnotationsAttributeData() []byte {
	return self.getUnparsedAttributeData("RuntimeVisibleAnnotations")
}

func (self *MemberInfo) RuntimeVisibleParameterAnnotationsAttributeData() []byte {
	return self.getUnparsedAttributeData("RuntimeVisibleParameterAnnotationsAttribute")
}

func (self *MemberInfo) AnnotationDefaultAttributeData() []byte {
	return self.getUnparsedAttributeData("AnnotationDefault")
}

func (self *MemberInfo) getUnparsedAttributeData(name string) []byte {
	for _, attrInfo := range self.attributes {
		switch attrInfo.(type) {
		case *UnparsedAttribute:
			unparsedAttr := attrInfo.(*UnparsedAttribute)
			attrName := self.__constantPool__.getUtf8(unparsedAttr.attributeNameIndex)
			if attrName == name {
				return unparsedAttr.info
			}
		}
	}
	return nil
}
